package com.s7.compat.exception;

import android.content.Context;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.os.Build;
import android.os.Looper;
import android.widget.Toast;

import com.s7.compat.listener.CrashHandlerListener;

import java.io.PrintWriter;
import java.io.StringWriter;
import java.lang.Thread.UncaughtExceptionHandler;
import java.text.SimpleDateFormat;
import java.util.Date;


public class CrashHandler implements UncaughtExceptionHandler {

    public static final String TAG = "CrashHandler";

    private UncaughtExceptionHandler mDefaultHandler;

    private static volatile CrashHandler instance;

    private Context mContext;

    private CrashHandlerListener mListener;


    public CrashHandler() {
    }


    public static CrashHandler getInstance() {
        if (instance == null)
            synchronized (CrashHandler.class) {
                if (instance == null) {
                    instance = new CrashHandler();
                }
            }
        return instance;
    }


    public CrashHandler init(Context context) {
        mContext = context;

        mDefaultHandler = Thread.getDefaultUncaughtExceptionHandler();

        Thread.setDefaultUncaughtExceptionHandler(this);
        return this;
    }

    public CrashHandler init(Context context, CrashHandlerListener mListener) {
        mContext = context;
        this.mListener = mListener;

        mDefaultHandler = Thread.getDefaultUncaughtExceptionHandler();

        Thread.setDefaultUncaughtExceptionHandler(this);
        return this;
    }

    @Override
    public void uncaughtException(Thread thread, Throwable throwable) {
        if (!handleException(throwable) && mDefaultHandler != null) {

            mDefaultHandler.uncaughtException(thread, throwable);
        } else {

            try {
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            if (mListener != null) {
                mListener.onException();
            }
        }
    }

    protected boolean handleException(Throwable ex) {

        if (ex == null || mContext == null)
            return false;

        try {
            savcExceptionToData(ex);
        } catch (Exception e) {
            e.printStackTrace();
        }

        new Thread(new Runnable() {
            public void run() {
                Looper.prepare();
                Toast.makeText(mContext, "很抱歉,程序出现异常,即将退出。", Toast.LENGTH_SHORT).show();
                Looper.loop();
            }
        }).start();
        return true;

    }

    private void savcExceptionToData(final Throwable ex) throws Exception {

        SimpleDateFormat formatdate = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        final String time = formatdate.format(new Date(System.currentTimeMillis()));

        CrashHandlerData data = new CrashHandlerData();
        data.setTime(time);
        savePhoneInfo(data, ex);

        if (mListener != null) {
            mListener.onExceptionData(data);
        }

    }

    private void savePhoneInfo(CrashHandlerData data, Throwable ex) throws PackageManager.NameNotFoundException {
        PackageManager pm = mContext.getPackageManager();
        PackageInfo pi = pm.getPackageInfo(mContext.getPackageName(), PackageManager.GET_ACTIVITIES);

        StringWriter sw = new StringWriter();
        PrintWriter pw = new PrintWriter(sw);
        ex.printStackTrace(pw);

        data.setApp_versionName(pi.versionName);
        data.setApp_versionCode(pi.versionCode);
        data.setOS_Version(Build.VERSION.RELEASE);
        data.set_sdk(Build.VERSION.SDK_INT);
        data.setVendor(Build.MANUFACTURER);
        data.setModel(Build.MODEL);
        data.setCPU_ABI(Build.CPU_ABI);
        data.setThrowable(sw.toString());
    }
}
